﻿using System;
using System.IO;
using EfficientlyLazy.PhotoFramer.Entity;
using EfficientlyLazy.PhotoFramer.Repository;
using FluentMigrator.Runner.Announcers;
using FluentMigrator.Runner.Initialization;
using EfficientlyLazy.PhotoFramer.Service;

namespace EfficientlyLazy.PhotoFramer
{
    internal class Loader
    {
        internal readonly static string DbPath;
        internal static readonly string ConnectionString;

        static Loader()
        {
            var rootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "PhotoFramer");

            if (!Directory.Exists(rootPath))
            {
                Directory.CreateDirectory(rootPath);
            }

            DbPath = Path.Combine(rootPath, "PhotoFramer.db");
            ConnectionString = string.Format("Data Source={0};Version=3;Password=PhotoFramerPassword", DbPath);
        }

        internal static void Start()
        {
            Start(false);
        }

        internal static void Start(bool purgeExistingDatabase)
        {
            if (purgeExistingDatabase)
            {
                PurgeExistingDatabase();
            }

            RunMigrations();
            RegisterAssemblies();
        }

        private static void PurgeExistingDatabase()
        {
            if (File.Exists(DbPath))
            {
                File.Delete(DbPath);
            }
        }

        private static void RunMigrations()
        {
            var connection = new System.Data.SQLite.SQLiteConnection(ConnectionString);
            var announcer = new NullAnnouncer();
            var context = new RunnerContext(announcer);
            var generator = new FluentMigrator.Runner.Generators.SQLite.SqliteGenerator();
            var options = new FluentMigrator.Runner.Processors.ProcessorOptions();
            var processor = new FluentMigrator.Runner.Processors.Sqlite.SqliteProcessor(connection, generator, announcer, options);

            var runner = new FluentMigrator.Runner.MigrationRunner(typeof(Loader).Assembly, context, processor);

            runner.MigrateUp();
        }

        private static void RegisterAssemblies()
        {
            ServiceFactory.WithAssembly(typeof (Loader).Assembly)
                .RegisterByAttribute<ServiceFactoryAttribute>();

            ServiceFactory.WithAssembly(typeof(Loader).Assembly)
                .RegisterByInterface<IWriteable>()
                .Bind(typeof(IRepository<>), typeof(Repository<>));
        }
    }
}
